
#pragma once

#include <ttg/services.h>
#include <ttg/utils.h>
#include "Common/ICalculationCore.h"
#include "Kernel.h"

using namespace ttg::utils;

//Version, that uses "pure" CUDA (code has been written according to SDK samples).
class cudaCore :public ICalculationCore
{
	private:
		ParameterSet *cuda_filter;
		ParameterEnum *block_size;
		std::vector<size_t> block_size_values;
	public:
		//Creating parameters.
		inline cudaCore()
		{
			cuda_filter = new ParameterSet("Pure CUDA settings"),
			block_size = new ParameterEnum("blockDim.x", cuda_filter, "64|128|256|512|1024");
			block_size_values.push_back(64);
			block_size_values.push_back(128);
			block_size_values.push_back(256);
			block_size_values.push_back(512);
			block_size_values.push_back(1024);
		}

		virtual double simulate(InterleavedBodies::SubVector bodies, float dt)
		{
			InterleavedBodies *owner = bodies.getOwner();
			double t_start = ttg::services::Timer::getRef()->getSeconds();
			interactAndUpdate(owner->positions.getX(), owner->positions.getY(), owner->positions.getZ(),
							  owner->velocities.getX(), owner->velocities.getY(), owner->velocities.getZ(),
							  owner->accelerations.getX(), owner->accelerations.getY(), owner->accelerations.getZ(),
							  &owner->masses[0], bodies.getSize(), block_size_values[*block_size]);
			double t_end = ttg::services::Timer::getRef()->getSeconds();
			return t_end - t_start;
		}
		virtual ~cudaCore()
		{
			SAFE_DELETE(block_size);
			SAFE_DELETE(cuda_filter);
		}
};
